/*
 */
package org.hook.showcase.concurrent.tools;

import java.util.ArrayList;
import java.util.concurrent.Exchanger;

/**
 * @author suwuqiang 2011-12-22
 */
public class ExchangerCase {
	private static Exchanger<ArrayList<Integer>> exchanger = null;
	private static ArrayList<Integer> buffer1 = null;
	private static ArrayList<Integer> buffer2 = null;

	private static class Producer extends Thread {
		@Override
		public void run() {
			ArrayList<Integer> buff = buffer1;
			try {
				while (true) {
					if (buff.size() >= 10) {
						// 与consumer交换buffer.
						System.out.println("producer: exchanging...");
						buff = exchanger.exchange(buff);
						buff.clear();
					}
					// 随机产生一个0-100的整数。
					int x = (int) (Math.random() * 100);
					buff.add(x);
					System.out.println("producer: " + x);
					// 随机等待0-3秒 。
					int t = (int) (Math.random() * 3);
					Thread.sleep(t * 1000);
				}
			} catch (InterruptedException e) {
				System.out.println("producer: interrupted.");
			}
		}
	}

	private static class Consumer extends Thread {
		@Override
		public void run() {
			ArrayList<Integer> buff = buffer2;
			try {
				while (true) {
					for (Integer x : buff) {
						System.out.println("consumer: " + x);
						// 随机等待0-3秒 。
						int t = (int) (Math.random() * 3);
						Thread.sleep(t * 1000);
					}
					// 与producer交换buffer。
					System.out.println("consumer: exchanging...");
					buff = exchanger.exchange(buff);
				}
			} catch (InterruptedException e) {
				System.out.println("consumer: interrupted.");
			}
		}
	}

	public static void main(String[] args) throws InterruptedException {
		exchanger = new Exchanger<ArrayList<Integer>>();
		buffer1 = new ArrayList<Integer>(10);
		buffer2 = new ArrayList<Integer>(10);
		Thread pth = new Producer();
		Thread cth = new Consumer();
		pth.start();
		cth.start();
		Thread.sleep(60 * 1000);
		System.out.println("main: interrupting threads...");
		pth.interrupt();
		cth.interrupt();
		pth.join();
		cth.join();
		System.out.println("main: end.");
	}
}
